
package com.lgcns.android2;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnCancelListener;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.ProgressBar;
import android.widget.Toast;

public class SplashActivity extends Activity {

    public static String TAG = MainActivity.TAG;

    private final static int DIALOG_CONFIRM_DOWNLOAD = 1;
    private final static int DIALOG_UPDATE_CHECK = 2;
    private final static int DIALOG_ERROR_DB_INFO = 3;
    private final static int DIALOG_ERROR_DB_DOWNLOAD = 4;
    
    private ProgressDialog mProgressDialog;
    private ProgressBar mProgressBar;

    private DBInfoItem mDbInfo;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.splash);

        mProgressBar = (ProgressBar) findViewById(R.id.dbDownloadProgressBar);
        
        // STEP 1. DB 데이터가 존재하는지 확인
        SharedPreferences prefs = getSharedPreferences(Constants.DB_VERSION_KEY, Context.MODE_PRIVATE);
        String currentDbVersion = prefs.getString(Constants.DB_VERSION_KEY, "");

        // STEP 2. DB 가 존재하지 않으면 지정된 위치에서 DB 파일 정보 얻고 다운로드 시작
        if (!"".equals(currentDbVersion)) {
            startMainActivity(Constants.SPLASH_ANIM_DURATION);
        } else {
            showDialog(DIALOG_CONFIRM_DOWNLOAD);
        }
    }

    @Override
    public Dialog onCreateDialog(int id) {
        if (id == DIALOG_CONFIRM_DOWNLOAD) {
            // DB 다운로드 확인 창
            return new AlertDialog.Builder(this)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setTitle("Inform")
            .setMessage("DB 다운로드가 필요합니다.\n\n시작하시겠습니까?")
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    showDialog(DIALOG_UPDATE_CHECK);
                }
            })
            .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    finish();
                    return;
                }
            })
            .create();
        } else if (id == DIALOG_UPDATE_CHECK) {
            // DB 정보 체크 진행창 
            mProgressDialog = new ProgressDialog(SplashActivity.this);
            
            DBInfoJob job = new DBInfoJob();
            job.execute();
            
            return mProgressDialog;
        } else if (id == DIALOG_ERROR_DB_INFO) {
            // DB info 다운로드 에러  창
            return new AlertDialog.Builder(this)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setTitle("Error")
            .setMessage("최신 DB 정보를 가져올 수 없습니다.")
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    finish();
                    return;
                }
            })
            .create();
        } else if (id == DIALOG_ERROR_DB_DOWNLOAD) {
            // DB 파일 다운로드 에러  창
            return new AlertDialog.Builder(this)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setTitle("Error")
            .setMessage("DB 다운로드 중 오류가 발생하였습니다.")
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    finish();
                    return;
                }
            })
            .create();
        }

        return null;
    }

    /**
     * 특정 시간 이후 MainActivity 실행 
     * 
     * @param animDuration
     */
    private void startMainActivity(int animDuration) {
        
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {

            @Override
            public void run() {
                Intent intent = new Intent(SplashActivity.this, MainActivity.class);
                startActivity(intent);
                SplashActivity.this.finish();
                
                overridePendingTransition(R.anim.fadein, R.anim.hold);
            }
            
        }, animDuration);
    }

    /**
     * 최신 Profile DB 정보를 서버로부터 가져오는 AsyncTask
     * 
     * DB 버전 및 DB 정보 파일 사이즈를 얻는다.
     * 
     * @author kim.jiseong
     */
    private class DBInfoJob extends AsyncTask<String, Integer, Long> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            mProgressDialog.setMessage("Checking...");
            mProgressDialog.setCancelable(true);
            mProgressDialog.setOnCancelListener(new OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    Toast.makeText(SplashActivity.this, "Cancel...", Toast.LENGTH_SHORT);
                }
            });
            
            mProgressDialog.show();
        }

        @Override
        protected Long doInBackground(String... strData) {

            StringBuilder sb = new StringBuilder();
            BufferedReader br = null;

            try {
                URL url = new URL(Constants.DB_INFO_URL);
                HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
                httpConn.setDoOutput(true);
                httpConn.setUseCaches(false);

                br = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
                
                String temp;
                
                while((temp=br.readLine()) != null) {
                    sb.append(temp);
                }

                JSONObject jsonObj = new JSONObject(sb.toString());
                
                String dbVersion = jsonObj.getString("db_version");
                String dbFileSize = jsonObj.getString("file_size");

                mDbInfo = new DBInfoItem();
                mDbInfo.dbVersion = dbVersion;
                mDbInfo.dbFileSize = Integer.parseInt(dbFileSize);

                Log.v(TAG, "db version : " + dbVersion + ", fileSize : " + dbFileSize);
            } catch (Exception e) {
                Log.e(TAG, e.getMessage());

                return -1L;
            } finally {
                Util.closeSilently(br);
            }

            return 0L;
        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            
        }
        
        @Override
        protected void onPostExecute(Long result) {
            mProgressDialog.dismiss();

            if (result == -1L) {
                showDialog(DIALOG_ERROR_DB_INFO);
            } else { 
                DBDownloadJob job = new DBDownloadJob();
                job.execute();
            }
        }
        
        @Override
        protected void onCancelled() {
            super.onCancelled();
        }
    }

    /**
     * 지정된 URL로부터 DB 파일을 다운로드 하여 DB 정보를 갱신하는 AsyncTask class
     * 
     * @author kim.jiseong
     */
    private class DBDownloadJob extends AsyncTask<String, Integer, Long> {

        private File mTempFile; 

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            
            mProgressBar.setMax(mDbInfo.dbFileSize);
            mProgressBar.setVisibility(View.VISIBLE);
            
            Log.d(TAG, "Profile DB is about to download");
        }

        @Override
        protected Long doInBackground(String... strData) {

            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;

            byte[] buf = new byte[4096];

            try {
                URL url = new URL(Constants.DB_URL);
                HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
                httpConn.setDoOutput(true);
                httpConn.setUseCaches(false);

                bis = new BufferedInputStream(httpConn.getInputStream(), 4096);

                // SDCARD 임시 파일에 다운로드
                mTempFile = File.createTempFile(getPackageName(), null);
                bos = new BufferedOutputStream(new FileOutputStream(mTempFile));

                int cnt = 0;
                int rcvBytes = 0;

                while((cnt = bis.read(buf)) != -1) {
                    bos.write(buf , 0, cnt);

                    rcvBytes += cnt;
                    publishProgress(rcvBytes);
                }

                bos.flush();

            } catch (Exception e) {
                Log.e(TAG, e.getMessage());
                
                return -1L;
            } finally {
                Util.closeSilently(bis);
                Util.closeSilently(bos);
            }
            
            return 0L;
        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            mProgressBar.setProgress(progress[0]);
        }
        
        @Override
        protected void onPostExecute(Long result) {
            if (result == -1L) {
                showDialog(DIALOG_ERROR_DB_DOWNLOAD);
            } else {
                DatabaseHelper dbHelper = new DatabaseHelper(getBaseContext());
                dbHelper.updateDatabase(mTempFile);
    
                // ShasredPreference에 DB 버전 기록
                SharedPreferences prefs = getSharedPreferences(Constants.DB_VERSION_KEY, Context.MODE_PRIVATE);
                SharedPreferences.Editor editor = prefs.edit();
                editor.putString(Constants.DB_VERSION_KEY, mDbInfo.dbVersion);
                editor.commit();

                Log.d(TAG, "Profile DB has updated to " + mDbInfo.dbVersion);

                Toast.makeText(SplashActivity.this, "업데이트가 완료되었습니다.", Toast.LENGTH_LONG).show();

                startMainActivity(100);
            }
            
            if (mTempFile != null) {
                mTempFile.delete();
            }
        }
        
        @Override
        protected void onCancelled() {
            super.onCancelled();
            
            Log.e(TAG, "onCancelled");
        }
    }
    
}
